package com.duartepeixinho.P3D.Core.Math
{
	/**
	 * P3D
	 * @version 0.1
	 * @author Duarte Peixinho
	 */
	public class Vector2
	{
		
		protected var _x:Number;
		protected var _y:Number;
		
		public function Vector2(x:Number=0,y:Number=0) 
		{
			_x = x;
			_y = y;
		}
		
		// Getters & Setters
		public function get x():Number {
			return _x;
		}
		public function get y():Number {
			return _y;
		}
		public function set x(x:Number):void {
			_x = x;
		}
		public function set y(y:Number):void {
			_y = y;
		}
		
		
		// Vector Calculations
		
		/**
		 * Add Value
		 * @param	value	Number	Value to Add
		 * @return			Vector2	Returns changed vector
		 */
		protected function addValue(value:Number):Vector2 {
			return new Vector2(_x + value, _y + value);
		}
		
		/**
		 * Subtract Value
		 * @param	value	Number	Value to Subtract
		 * @return			Vector2	Returns changed vector
		 */
		protected function subValue(value:Number):Vector2 {
			return new Vector2(_x - value, _y - value);
		}
		
		/**
		 * Multiply Value
		 * @param	value	Number	Value to Multiply
		 * @return			Vector2	Returns changed vector
		 */
		public function multValue(value:Number):Vector2 {
			return new Vector2(_x * value, _y * value);
		}
		
		/**
		 * Divide Value
		 * @param	value	Number	Value to Divide
		 * @return			Vector2	Returns changed vector
		 */
		public function divValue(value:Number):Vector2 {
			return new Vector2(_x / value, _y / value);
		}
		
		/**
		 * Add Vector
		 * @param	vector	Vector2	Vector to Add
		 * @return			Vector2	Returns changed vector
		 */
		public function addVector(vector:Vector2):Vector2 {
			return new Vector2(_x + vector.x, _y + vector.y);
		}
		
		/**
		 * Subtract Vector
		 * @param	vector	Vector2	Vector to Subtract
		 * @return			Vector2	Returns changed vector
		 */
		public function subVector(vector:Vector2):Vector2 {
			return new Vector2(_x - vector.x, _y - vector.y);
		}
		
		/**
		 * Multiply Vector
		 * @param	vector	Vector2	Vector to Multiply
		 * @return			Vector2	Returns changed vector
		 */
		public function multVector(vector:Vector2):Vector2 {
			return new Vector2(_x * vector.x, _y * vector.y);
		}
		
		/**
		 * Divide Vector
		 * @param	vector	Vector2	Vector to Divide
		 * @return			Vector2	Returns changed vector
		 */
		public function divVector(vector:Vector2):Vector2 {
			return new Vector2(_x / vector.x, _y / vector.y);
		}
		
		/**
		 * Dot Product
		 * @param	vector	Vector2	
		 * @return					Dot Product
		 */
		public function dotProduct(vector:Vector2):Number {
			return (_x * vector.x) + (_y * vector.y);
		}
		
		/**
		 * Compare Vector
		 * @param	vector	Vector2	Vector to compare
		 * @return			Boolean	Return comparision
		 */
		public function compareVector(vector:Vector2):Boolean {
			return (_x == vector.x) && (_y == vector.y);
		}
		
		/**
		 * Length
		 * @return					Returns Vector Length
		 */
		public function length():Number {
			return Math.sqrt(this.lengthSq());
		}
		
		/**
		 * Length SQR
		 * @return					Returns Vector Length SQR
		 */
		public function lengthSq():Number {
			return _x * _x + _y * _y;
		}
		
		/**
		 * Vector Negate
		 */
		public function negate():void {
			_x = -_x;
			_y = -_y;
		}
		
		/**
		 * Distance
		 * @param	vector	Vector2	Vector to get distance
		 * @return			Number	Returns Distance to Vector
		 */
		public function distance(vector:Vector2):Number {
			var v:Vector2 = this.subVector(vector);
			return v.length();
		}
		/**
		 * Distance SQ
		 * @param	vector	Vector2	Vector to get distance
		 * @return			Number	Returns Distance SQ to Vector
		 */
		public function distanceSq(vector:Vector2):Number {
			var v:Vector2 = this.subVector(vector);
			return v.lengthSq();
		}		
		/**
		 * Normalize Vector
		 */
		public function normalize():void {
			var m:Number = this.length();
			if (m == 0) m = 1;
			_x /= m;
			_y /= m;
		}
		
		/**
		 * Normalize Vector
		 * @return			Vector2	Retuns normalize Vector
		 */
		public function returnNormalize():Vector2 {
			var m:Number = this.length();
			if (m == 0) m = 1;
			return new Vector2(_x /= m, _y /= m);
		}
		
		/**
		 * Copy Vector
		 * @param	vector	Vector2	Vector to copy
		 */
		public function copy(vector:Vector2):void {
			_x = vector.x;
			_y = vector.y;
		}
		
		/**
		 * Clone Vector
		 * @return			Vector2	Returns a new Vector
		 */
		public function clone():Vector2 {
			return new Vector2(_x, _y);
		}
		
		/**
		 * toString
		 * @return			String	Returns vector in a String
		 */
		public function toString():String {
			return "Vector2(" + _x.toString() + "," + _y.toString() + ")";
		}
		
	}

}